import { Asset, JsonAsset, SpriteFrame } from 'cc';
import { LoadingBundle } from '../Config/BaseEnum';
import { Singleton } from '../Manager/BaseManager';
import { LoadingManager } from '../Manager/LoadingManager';

/*eslint-disable*/
export abstract class ModelBase extends Singleton {
  /** 动态资源 */
  private _dynamicsRes: Map<string, Asset> = new Map<string, Asset>();
  /** 加载动态资源 */
  async loadDynamicResByBundle<T extends Asset>(bundle: LoadingBundle, loadRes: string[]): Promise<T[]> {
    const temp: string[] = [];
    const result = [];
    loadRes.forEach((res) => {
      const ss = bundle + '/' + res;
      if (this._dynamicsRes.has(ss)) {
        result.push(this._dynamicsRes.get(ss));
      } else {
        temp.push(res);
      }
    });
    if (temp.length > 0) {
      const res = await LoadingManager.Ins().loadDynamicsResByBundle<T>(bundle, temp);
      for (let i = 0; i < res.length; i++) {
        this._dynamicsRes.set(bundle + '/' + temp[i], res[i]);
        result.push(res[i]);
      }
    }
    return result as T[];
  }

  /** 加载动态资源 */
  async loadDynamicRes<T extends Asset>(loadRes: string): Promise<T>;
  async loadDynamicRes<T extends Asset>(loadRes: string[]): Promise<T[]>;
  async loadDynamicRes<T extends Asset>(loadRes: string | string[]): Promise<T | T[]> {
    if (Array.isArray(loadRes)) {
      const temp: string[] = [];
      const result = [];
      loadRes.forEach((res) => {
        if (this._dynamicsRes.has(res)) {
          result.push(this._dynamicsRes.get(res));
        } else {
          temp.push(res);
        }
      });
      if (temp.length > 0) {
        const res = await LoadingManager.Ins().loadDynamicsRes<T>(temp);
        for (let i = 0; i < res.length; i++) {
          this._dynamicsRes.set(temp[i], res[i]);
          result.push(res[i]);
        }
      }
      return result as T[];
    } else {
      const res = this._dynamicsRes.get(loadRes);
      if (res == null) {
        return await LoadingManager.Ins().loadDynamicsRes<T>(loadRes);
      } else {
        return res as T;
      }
    }
  }

  /** 释放动态资源 */
  releaseDynamicResByBundle(bundle: LoadingBundle, loadRes: string[]) {
    loadRes.forEach((res) => {
      const ss = bundle + '/' + res;
      if (!this._dynamicsRes.has(res)) return;
      LoadingManager.Ins().releaseDynamicRes(res);
      this._dynamicsRes.delete(res);
    });
  }

  /** 释放动态资源 */
  releaseDynamicRes(loadRes?: string | string[]) {
    if (loadRes) {
      if (Array.isArray(loadRes)) {
        loadRes.forEach((res) => {
          if (!this._dynamicsRes.has(res)) return;
          LoadingManager.Ins().releaseDynamicRes(res);
          this._dynamicsRes.delete(res);
        });
      } else {
        const res = this._dynamicsRes.get(loadRes);
        if (res) {
          LoadingManager.Ins().releaseDynamicRes(loadRes);
          this._dynamicsRes.delete(loadRes);
        }
      }
    } else {
      this._dynamicsRes.forEach((res, key) => {
        // res.decRef();
        LoadingManager.Ins().releaseDynamicRes(key);
      });
      this._dynamicsRes.clear();
    }
  }

  /** 加载远程图片资源 */
  private _spriteFrameRes: Map<string, SpriteFrame> = new Map();
  async loadSpriteRemote(
    url: string,
    options?: {
      [k: string]: any;
      ext?: string;
    }
  ): Promise<SpriteFrame> {
    let sp: SpriteFrame = null;
    if (this._spriteFrameRes.has(url)) {
      return this._spriteFrameRes.get(url);
    } else {
      sp = await LoadingManager.Ins().loadResRemote(url, options);
    }
    return sp;
  }

  private _jsonRes: Map<string, JsonAsset> = new Map();
  async loadJsonRemote(url: string): Promise<JsonAsset> {
    let json: JsonAsset = null;
    if (this._jsonRes.has(url)) {
      return this._jsonRes.get(url);
    } else {
      json = await LoadingManager.Ins().loadResRemote2(url);
    }
    return json;
  }

  releaseRemoteSprite(loadRes?: string | string[]) {
    if (loadRes) {
      if (Array.isArray(loadRes)) {
        loadRes.forEach((res, key) => {
          if (!this._spriteFrameRes.has(res)) return;
          LoadingManager.Ins().releaseRemoteSprite(this._spriteFrameRes.get(res));
          this._spriteFrameRes.delete(res);
        });
      } else {
        const res = this._spriteFrameRes.get(loadRes);
        if (res) {
          LoadingManager.Ins().releaseRemoteSprite(res);
          this._spriteFrameRes.delete(loadRes);
        }
      }
    } else {
      this._spriteFrameRes.forEach((sp) => {
        LoadingManager.Ins().releaseRemoteSprite(sp);
      });
      this._spriteFrameRes.clear();
    }
  }
}
